#include<iostream>
#include<vector>
#include<cassert>
#include<ctime>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include"Task.hpp"
using namespace std;

#define PROCNUM 4

int WaitForCommand(int fd, bool& quit)
{
    uint32_t command = 0;
    ssize_t sz = read(fd, &command, sizeof(command));
    if(sz == 0)
    {
        quit = true;
        return -1;
    }
    assert(sz == sizeof(uint32_t));
    return command;
}

void WakeupProcess(int whichPro, int pipefd, int command)
{
    write(pipefd, &command, sizeof(command));
    cout << "write to " << whichPro << " : " << command << " though " << pipefd << endl;
}

int main()
{
    int pipefd[2] = {0};
    vector<pair<pid_t, int>> proVP;
    Load();     //这个函数调用需要在前面先调用，否则会出错
    for(int i = 0; i < PROCNUM; ++i)
    {
        int ret = pipe(pipefd);
        assert(ret != -1);
        pid_t id = fork();
        assert(id != -1);
        if(id == 0)
        {
            close(pipefd[1]);
            while(true)
            {
                bool quit = false;
                int command = WaitForCommand(pipefd[0], quit);
                if(quit)
                    break;
                //cout<<command<<endl;
                if(command >= 0 && command < HandlerSize())
                    loadFun[command]();
                else
                    cout << "error command : " << command << " " << getpid() << endl;
            }
            exit(0);    //执行结束直接退出即可
        }
        //cout<<pipefd[0]<<" "<<pipefd[1]<<endl;
        close(pipefd[0]);
        proVP.push_back(make_pair(id, pipefd[1]));      //传读端，在下方是父进程在用
    }
    int option;
    srand(time(nullptr) ^ 187153484131354);
    while(true)
    {
        cout << "************************************" << endl;
        cout << "****** 1.show         2.selete   ***" << endl;
        cout << "************************************" << endl;
        cout << "请输入你的选择> ";
        cin >> option;
        if(option == 1)
        {
            Show();
        }
        else if(option == 2)
        {
            int command;
            cout << "请输入你的选择> ";
            cin >> command;
            //cout<<pipefd[0]<<" "<<pipefd[1]<<endl;
            int choice = rand() % proVP.size();     //此处是选择进程，所以应该用proVP的大小而不是调用HandlerSize
            WakeupProcess(proVP[choice].first, proVP[choice].second, command);
            //cout<<choice<<endl;
            sleep(1);
            
        }
        else
        {
            cout << "error, try again" << endl;
        }
    }
    for(const auto& it : proVP)
    {
        close(it.second);
    }

    // for(int i = 0; i < PROCNUM; ++i)
    // {
    //     waitpid(-1, nullptr, 0);
    // }

    //直接指定要等待哪个进程
    for(const auto& it : proVP)
    {
        waitpid(it.first, nullptr, 0);
    }

    return 0;
}